#include "Logstream.h"

#include <cstdint>
#include <cstdio>
#include <cstring>

namespace _ {

static std::size_t htoa(char *buffer, uintptr_t value) {
    auto v = value;
    static constexpr auto HEX_DIGIT = "0123456789abcdef";
    auto *p = buffer;
    do {
        *p++ = HEX_DIGIT[static_cast<int>(v % 0x10)];
        v /= 0x10;
    } while (v != 0);
    *p = '\0';
    std::reverse(buffer, p);
    return static_cast<std::size_t>(p - buffer);
}

}


Logstream &Logstream::operator<<(double d) {
    if (_buffer.available_length() >= _MAX_NUMERIC_LENGTH) {
        _buffer.add(static_cast<std::size_t>(
            ::snprintf(_buffer.current(), _MAX_NUMERIC_LENGTH, "%.12g", d)));
    }
    return *this;
}

Logstream &Logstream::operator<<(const std::string_view &str) {
    if (str.empty()) {
        return operator<<("(null)");
    }
    _buffer.append(str.data(), str.size());
    return *this;
}

Logstream &Logstream::operator<<(const void *ptr) {
    if (_buffer.available_length() > _MAX_NUMERIC_LENGTH) {
        auto *buffer = _buffer.current();
        buffer[0] = '0';
        buffer[1] = 'x';
        _buffer.add(_::htoa(buffer + 2, reinterpret_cast<uintptr_t>(ptr)) + 2);
    }
    return *this;
}